function Shape () {
    this.x = undefined;
    this.y = undefined;
    this.strokeStyle = 'rgba(255, 253, 208, .9)';
    this.fillStyle = 'rgba(147, 197, 114, .8)';
    return this;
}

Shape.prototype = {
    /**
     * 检测当前形状与受测形状是否发生了碰撞
     * @param {Shape} 受测形状
     * @returns {Boolean} 是否发生碰撞
     */
    collidesWith: function (otherShape) {
        var axes = this.getAxes().concat(otherShape.getAxes());
        return !this.separationOnAxes(axes, otherShape);
    },

    /**
     * 循环每一条投射轴，检测当前形状与指定受测形状是否分离
     * @param {Array} 当前与受测形状所有的投影轴
     * @param {Shape} 受测形状
     * @return {Boolean} 两个形状是否分离
     */
    separationOnAxes: function (axes, otherShape) {
        for(var i = 0; i < axes.length; i += 1) {
            var axis = axes[i];
            var projection1 = otherShape.project(axis);
            var projection2 = this.project(axis);
            if( !projection1.overlaps(projection2) ) {
                return true;
            }
        }
        return false;
    },

    /**
     * 获取最小平移向量
     * @param {Array[VectorB]} 所有投影轴
     * @param {Shape} 受测对象
     * @return {MinimumTranslationVector} 返回最小平移向量
     */
    minimumTranslationVector: function (axes, shape) {
        var minimumOverlap = 100000,
            overlap,
            axisWithSmallestOverlap,
            axis, projection1, projection2;
        for(var i = 0; i < axes.length; i += 1) {
            axis = axes[i];
            projection1 = shape.project(axis);
            projection2 = this.project(axis);
            overlap = projection1.overlap(projection2);
            if(overlap === 0) {
                //没有碰撞发生
                return new MinimumTranslationVector(undefined, 0);
            } else {
                //有碰撞发生
                if(overlap < minimumOverlap) {
                    minimumOverlap = overlap;
                    axisWithSmallestOverlap = axis;
                }
            }
        }
        return new MinimumTranslationVector(axisWithSmallestOverlap, minimumOverlap);
    },

    /**
     * 获取所有投影轴
     */
    getAxes: function () {
        //这里的作用更像一个接口的声明，具体实现依赖于 Polygon和circle类 的重写
        //下面的 project 也一样
        throw new Error('getAxes 还未实现');
    },

    /**
     * 获取投影对象
     */
    project: function (axis) {
        throw new Error('project 还未实现');
    },

    /**
     * 移动方式
     */
    move: function () {
        throw new Error('move 还未实现');
    },

    //绘制方法··················································
    /**
     * 创建路径
     */
    createPath: function (ctx) {
        throw new Error('createPath 还未实现');
    },

    /**
     * 填充函数
     */
    fill: function (ctx) {
        ctx.save();
        ctx.fillStyle = this.fillStyle
        this.createPath(ctx);
        ctx.fill();
        ctx.restore();
    },

    /**
     * 描边函数
     */
    stroke: function (ctx) {
        ctx.save();
        ctx.strokeStyle = this.strokeStyle;
        this.createPath(ctx);
        ctx.stroke();
        ctx.restore();
    },

    /**
     * 判断给定点是否在路径上
     */
    isPointInPath: function (ctx, x, y) {
        this.createPath(ctx);
        return ctx.isPointInPath(x, y);
    }
}